package com.googlecode.gendevcode.common;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.googlecode.gendevcode.model.ProjectXml;
import com.googlecode.gendevcode.model.ServiceConfigXml;
import com.googlecode.gendevcode.model.pdm.DataTypePdmXml;

/**
 * 通用缓存类
 * @author devilishking
 *
 */
public class Cache {
	/**
	 * 程序上下文
	 */
	private ApplicationContext ctx;
	/**
	 * 程序根目录
	 */
	private String rootPath;
	/**
	 * 系统类配置信息集合
	 */
	private Map<String, ServiceConfigXml> serviceConfigXmlMap;
	/**
	 * 项目类型列表
	 */
	private List<String> projectTypeList; 
	/**
	 * 项目信息列表
	 */
	private List<ProjectXml> projectXmlList; 
	/**
	 * 数据类型结构列表
	 */
	private List<DataTypePdmXml> dataTypePdmXmlList; 
	
	private Cache(){ }	
	private static final Cache instance = new Cache();
	
	public static Cache getInstance() {
		return instance;
	}
	
	/**
	 * 初始化数据
	 */
	public void init() throws Exception{
		ctx = new ClassPathXmlApplicationContext("server.xml");
		rootPath = System.getProperty("user.dir");
		serviceConfigXmlMap = ServiceConfigXml.init();
		projectTypeList = getBeanName(ServiceConfigXml.ID_PROJECTCONFIG);
		projectXmlList = ProjectXml.init();
		dataTypePdmXmlList = DataTypePdmXml.init();
	}
	
	/**
	 * 重置数据
	 * @throws Exception
	 */
	public void reset() throws Exception{
		projectXmlList = ProjectXml.init();
	}
	
	/**
	 * 获取系统类实体类
	 * @param serviceId 系统类
	 * @return
	 */
	public <T> T getBean(String serviceId, Class<T> objectClass) throws Exception{
		return getBean(serviceId, -1, objectClass);
	}
	
	/**
	 * 获取系统类实体类
	 * @param serviceId 系统类
	 * @param index     序号
	 * @return
	 */
	public <T> T getBean(String serviceId, int index, Class<T> objectClass) throws Exception{
		return getBean(serviceId, index, null, objectClass);
	}
	
	/**
	 * 获取系统类实体类
	 * @param serviceId 系统类
	 * @param index     序号
	 * @param version   版本号
	 * @return
	 */
	public <T> T getBean(String serviceId, int index, String version, Class<T> objectClass) throws Exception{
		ServiceConfigXml serviceConfigXml = serviceConfigXmlMap.get(serviceId);
		Map<String, List<String[]>> beanMap = serviceConfigXml.getBeanMap();
		List<String> beanList = getBeanName(serviceId);
		String beanName = beanList.get(index == -1 ? beanList.size()-1 : index);
		List<String[]> versionList = beanMap.get(beanName);
		String[] versions = new String[2];
		if (version == null){
			versions = versionList.get(versionList.size()-1);
		}
		else{
			for(String[] versionTmp : versionList){
				if (version.equals(versionTmp[0])){
					versions = versionTmp;
					break;
				}
			}
		}
		if (versions != null && versions[1] != null){
			return ctx.getBean(versions[1], objectClass);
		}
		else{
			throw new Exception("没有找到相关系统类!");
		}
	}

	/**
	 * 获得程序根目录
	 * @return
	 */
	public String getRootPath() {
		return rootPath;
	}
	
	/**
	 * 项目类型列表
	 * @return
	 */
	public List<String> getProjectTypeList() {
		return projectTypeList;
	}

	/**
	 * 获取项目信息列表
	 * @return
	 */
	public List<ProjectXml> getProjectXmlList() {
		return projectXmlList;
	}

	/**
	 * 获取数据类型结构列表
	 * @return
	 */
	public List<DataTypePdmXml> getDataTypePdmXmlList() {
		return dataTypePdmXmlList;
	}

	/**
	 * 获取实体类名列表
	 * @param serviceId 系统类
	 * @return
	 */
	private List<String> getBeanName(String serviceId){
		List<String> beanNameList = new ArrayList<String>();
		ServiceConfigXml serviceConfigXml = serviceConfigXmlMap.get(serviceId);
		Map<String, List<String[]>> beanMap = serviceConfigXml.getBeanMap();
		Iterator<Entry<String, List<String[]>>> it = beanMap.entrySet().iterator();
		while(it.hasNext()){
			Entry<String, List<String[]>> entry = it.next();
			beanNameList.add(entry.getKey());
		}
		Collections.sort(beanNameList);
		return beanNameList;
	}
}